package com.shan.tools.starter.datasource;

import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * 数据库属性配置类
 **/
@Data
@ConfigurationProperties(prefix = "spring.jdbc")
public class DataSourceProperties {

    /**
     * 主库数据库链接url。格式: ip[:port]。
     */
    private String masterUrl;

    /**
     * 从库数据库url。格式: ip1[:port],ip2[:port]。
     */
    private List<String> slaveUrls;

    /**
     * 数据库实例名称
     */
    private String name;

    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;

    /**
     * 连接池中最多支持多少个活动会话
     */
    protected int maxActive = 20;

    /**
     * 回收空闲连接时，将保证至少有minIdle个连接.
     */
    protected int minIdle = 2;

    /**
     * 程序向连接池中请求连接时,超过maxWait的值后，认为本次请求失败，即连接池没有可用连接，单位毫秒，设置-1时表示无限等待
     * 获取连接时的最大等待时间, 单位毫秒. 配置了maxWait后, 缺省启用公平锁, 并发效率会有所下降, 如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
     */
    protected int maxWait = 10 * 1000;

    /**
     * 验证连接间隔时间
     */
    protected int validationInterval = 30000;

    /**
     * 单位：秒，检测连接是否有效的超时时间
     */
    protected int validationQueryTimeout = 5;

    /**
     * 检查空闲连接的频率，单位毫秒, 非正整数时表示不进行检查
     */
    protected int timeBetweenEvictionRunsMillis = 60 * 1000;

    /**
     * 程序没有close连接且空闲时长超过 minEvictableIdleTimeMillis,则会执行validationQuery指定的SQL,以保证该程序连接不会池kill掉,其范围不超过minIdle指定的连接个数。
     */
    private boolean keepAlive = true;

    /**
     * 池中某个连接的空闲时长达到 N 毫秒后, 连接池在下次检查空闲连接时，将回收该连接,要小于防火墙超时设置net.netfilter.nf_conntrack_tcp_timeout_established的设置
     * 回收时不管minIdle
     */
    protected int minEvictableIdleTimeMillis = 300000;

    /**
     * 启动程序时，在连接池中初始化多少个连接
     */
    protected int initialSize = 2;

    /**
     * 要求程序从池中get到连接后, N 秒后必须close,否则druid 会强制回收该连接,不管该连接中是活动还是空闲, 以防止进程不会进行close而霸占连接。
     */
    private boolean removeAbandoned=false;

    /**
     * 设置druid 强制回收连接的时限，当程序从池中get到连接开始算起，超过此值后，druid将强制回收该连接，单位秒。
     */
    protected int removeAbandonedTimeout = 60;

    /**
     * 当druid强制回收连接后，是否将stack trace 记录到日志中
     */
    private boolean logAbandoned = true;

    /**
     * 当程序请求连接，池在分配连接时，是否先检查该连接是否有效。(高效)
     */
    private boolean testWhileIdle = true;

    /**
     * 检查池中的连接是否仍可用的 SQL 语句,drui会连接到数据库执行该SQL, 如果正常返回，则表示连接可用，否则表示连接不可用
     */
    private String validationQuery="SELECT 1";

    /**
     * 程序 申请 连接时,进行连接时执行validationQuery检测连接是否有效有效性检查（低效，影响性能）
     */
    private boolean testOnBorrow = false;

    /**
     * 程序返还连接时执行validationQuery检测连接是否有效（低效，影响性能）
     */
    private boolean testOnReturn = false;

    /**
     *      缓存通过以下两个方法发起的SQL:	true
     *  	public PreparedStatement prepareStatement(String sql)
     *  	public PreparedStatement prepareStatement(String sql,int resultSetType, int resultSetConcurrency)
     */
    private boolean poolPreparedStatements = false;

    /**
     * 要启用PSSCache. 该配置必须大于0 如果该值大于0 则PoolPreparedStatements自动设置为true
     */
    private int maxOpenPreparedStatements = -1;

    /**
     * 每个连接最多缓存多少个SQL
     */
    private int maxPoolPrepareStatementPerConnectionSize = 20;

    /**
     * 这里配置的是插件,常用的插件有:	stat,wall,slf4j
     *  	监控统计: filter:stat
     *  	日志监控: filter:log4j 或者 slf4j
     *  	防御SQL注入: filter:wall
     */
    private String filters = "stat,wall";

    /**
     * 连接属性。比如设置一些连接池统计方面的配置。
     *  	druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
     *  	比如设置一些数据库连接属性:
     */
    private String connectProperties;

    /**
     * 合并多个DruidDataSource的监控数据
     */
    private boolean useGlobalDataSourceStat=true;

    /**
     * 数据库连接配置连接字符集也要设置为utf8mb4，否则在 严格模式 下会出现 Incorrect string value: /xF0/xA1/x8B/xBE/xE5/xA2… for column 'name’这样的错误，非严格模式下此后的数据会被截断
     */
    private Set<String> connectionInitSqls = Collections.singleton("set names utf8mb4");

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
    }
}
